package controllers

import (
	"github.com/gorilla/websocket"
	"log"
	"time"
	"github.com/astaxie/beego"
	//"github.com/astaxie/beego/toolbox"
	"fmt"
)

/**
 * 定义全局TCP连接
 */
var (
	// 存储所有的用户连接:clients(Uuid,wsConn)
	clients  = make(map[string]*websocket.Conn)
	// 广播数据
	broadcast = make(chan WsMessage)
	// Upgrader specifies parameters for upgrading an HTTP connection to a WebSocket connection.
	upgraders = websocket.Upgrader{}
)

type WsMessage struct {
	Uuid    string `json:"uuid"`
	Method    string `json:"method"`
	Key    string `json:"key"`
	Value string `json:"Value"`
	Message  string `json:"message"`
}

func init() {
	go handleMessages()
}
/**
 * 广播发送至客户端
 */
func handleMessages() {
	for {
		// Grab the next message from the broadcast channel
		msg := <-broadcast
		fmt.Println("clients len ", len(clients))
		// Send it out to every client that is currently connected
		for client := range clients {
			var val = clients[client]
			err := val.WriteJSON(msg)
			if err != nil {
				log.Printf("client.WriteJSON error: %v", err)
				val.Close()
				delete(clients, client)
			}
		}
	}
}

/**
 * 用户TCP注册
 */
type WebSocketController struct {
	beego.Controller
}
func (c *WebSocketController) Get() {
	// Upgrade initial GET request to a websocket
	ws, err := upgraders.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
	if err != nil {
		log.Fatal(err)
	}
	// Make sure we close the connection when the function returns
	defer ws.Close()

	// Register our new client
	uuid := c.Ctx.Input.Param(":uuid")
	if "" != uuid {
	}
	clients[uuid] = ws

	//如果从 socket 中读取数据有误，我们假设客户端已经因为某种原因断开。我们记录错误并从全局的 “clients” 映射表里删除该客户端，这样一来，我们不会继续尝试与其通信。
	//另外，HTTP 路由处理函数已经被作为 goroutines 运行。这使得 HTTP 服务器无需等待另一个连接完成，就能处理多个传入连接。
	for {
		time.Sleep(time.Second * 2)

		var msg WsMessage
		// Read in a new message as JSON and map it to a Message object
		err := ws.ReadJSON(&msg)
		if err != nil {
			log.Printf("页面可能断开啦 ws.ReadJSON error: %v", err)
			delete(clients, msg.Uuid)
			break
		}

		sendMessageToUser(&msg)
		//broadcast <- msg
	}
}

/**
 * 指定用户发送消息
 */
 // func (c *Conn) ReadJSON(v interface{}) error {
func sendMessageToUser(msg *WsMessage) {
	//var msg WsMessage;
	msg.Message = "测试正确"
	msg.Method = "测试方法"

	broadcast <- *msg
}